package com.hengpeng.common.scheduling;

import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.hengpeng.common.configuration.ConfigProvider;
import com.hengpeng.common.configuration.ConfigProviderFactory;

/**
 * <pre>
 * 任务调度控制类
 * </pre>
 * @author linriqing
 * @version 1.0, 2006-12-29
 */
public class ScheduleExcute
{
	private final static Map<String, ScheduleConfig> configMap = new HashMap<String, ScheduleConfig>();

	private final static Log logger = LogFactory.getLog(ScheduleExcute.class);

	private final static String SCHEDULE_CONFIG_FILEPATH = "schedule-config.xml";

	private final static Map<String, LotterySchedule> taskMap = new HashMap<String, LotterySchedule>();

	/**
	 * <pre>
	 * 获取所有的任务调度配置信息
	 * </pre>
	 * @return 所有的任务调度配置信息
	 */
	public static Map<String, ScheduleConfig> getAllScheduleConfig()
	{
		HashMap<String, ScheduleConfig> map = new HashMap<String, ScheduleConfig>();
		map.putAll(configMap);
		return map;
	}

	/**
	 * <pre>
	 * 获取任务调度描述说明
	 * </pre>
	 * @param scheduleconfig 任务调度的配置信息
	 * @return 任务调度描述说明
	 */
	public static String getIteratorDescription(ScheduleConfig scheduleconfig)
	{
		TimeIterator[] timeiterator = scheduleconfig.getIterator();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < timeiterator.length; i++)
		{
			TimeIterator iterator2 = timeiterator[i];
			String[] dayTimes = iterator2.getDaytimes();
			switch (iterator2.getRepeatMode())
			{
				// 任务不执行
				case -1:
					sb.append("迭代器[" + i + "]已经停止调度.");
					break;

				// 按千分之妙进行迭代
				case Calendar.MILLISECOND:
					sb.append("迭代器[" + i + "]每隔[" + iterator2.getInterval() + "]千分秒执行一次.");
					break;

				// 按分钟进行迭代
				case Calendar.MINUTE:
					sb.append("迭代器[" + i + "]在[");
					for (int j = 0; j < dayTimes.length; j++)
					{
						sb.append(dayTimes[j]);
						sb.append(",");
					}
					sb.append("]之间每隔[" + iterator2.getInterval() + "]分钟执行一次.");
					break;

				// 按天进行迭代
				case Calendar.DAY_OF_MONTH:
					sb.append("迭代器[" + i + "]每隔[");
					sb.append(iterator2.getInterval());
					sb.append("]天在[");
					for (int j = 0; j < dayTimes.length; j++)
					{
						sb.append(dayTimes[j]);
						sb.append(",");
					}
					sb.append("]执行一次.");
					break;

				// 默认按星期进行迭代
				case Calendar.DAY_OF_WEEK:
				default:
					int[] weekDays = iterator2.getWeekdays();
					sb.append("迭代器[" + i + "]每周[");
					for (int j = 0; j < weekDays.length; j++)
					{
						sb.append(weekDays[j]);
						sb.append(",");
					}
					sb.append("]在时间[");
					for (int j = 0; j < dayTimes.length; j++)
					{
						sb.append(dayTimes[j]);
						sb.append(",");
					}
					sb.append("]执行一次.");
					break;
			}
		}

		return sb.toString();
	}

	/**
	 * <pre>
	 * 获取以任务调度名称指定的任务调度配置信息
	 * </pre>
	 * @param taskName 任务调度名称
	 * @return 任务调度配置信息
	 */
	public static ScheduleConfig getScheduleConfig(String taskName)
	{
		return (ScheduleConfig) configMap.get(taskName);
	}

	/**
	 * <pre>
	 * 通过任务调度名称重新启动的任务
	 * </pre>
	 * @param taskName 任务调度名称
	 */
	public static void reloadTaskByName(String taskName)
	{
		if (ScheduleExcute.taskMap.size() > 0)
		{
			// 如果已经有任务实例在运行则先停止原来的任务.
			if (taskMap.containsKey(taskName))
			{
				ScheduleExcute.stopTaskByName(taskName);
			}
			ConfigProvider<ScheduleConfig> cp = ConfigProviderFactory.getInstance(SCHEDULE_CONFIG_FILEPATH,
					ScheduleConfig.class);
			cp.reloadConfigByPrimaryKey(taskName);
			ScheduleConfig config = (ScheduleConfig) cp.getConfigByPrimaryKey(taskName);
			ScheduleExcute.startTaskByConfig(config);
		}
	}

	/**
	 * <pre>
	 * 启动所有schedule-config.xml定义的任务调度
	 * </pre>
	 */
	public static void startAllTask()
	{
		if (ScheduleExcute.taskMap.size() > 0)
		{
			logger.error("当前有任务调度在执行，请先停止所有任务调度再启动所有任务调度.");
		}
		else
		{
			ConfigProvider<ScheduleConfig> cp = ConfigProviderFactory.getInstance(SCHEDULE_CONFIG_FILEPATH,
					ScheduleConfig.class);
			Map<String, ScheduleConfig> map = cp.getAllConfig();
			configMap.clear();
			for (Iterator<Entry<String, ScheduleConfig>> iter = map.entrySet().iterator(); iter.hasNext();)
			{
				Entry<String, ScheduleConfig> entry = iter.next();
				ScheduleConfig lconfig = (ScheduleConfig) entry.getValue();
				ScheduleExcute.startTaskByConfig(lconfig);
			}
			logger.info("所有任务调度启动完毕.");
		}
	}

	/**
	 * <pre>
	 * 通过任务调度配置启动的任务
	 * </pre>
	 * @param lconfig 任务调度配置
	 */
	public static void startTaskByConfig(ScheduleConfig lconfig)
	{
		if (taskMap.containsKey(lconfig.getKey()))
		{
			logger.error("任务调度[" + lconfig.getName() + "]已经有另一个实例启动.");
		}
		else
		{
			try
			{
				LotterySchedule logictask = new LotterySchedule(lconfig);
				// 开始任务侦听
				logictask.start();
				taskMap.put(lconfig.getKey(), logictask);
				configMap.put(lconfig.getKey(), lconfig);
				logger.info("任务调度[" + lconfig.getName() + "]开始启动, " + ScheduleExcute.getIteratorDescription(lconfig));
			}
			catch (Exception e)
			{
				logger.error("开始任务调度[" + lconfig.getName() + "]时异常", e);
			}
		}
	}

	/**
	 * <pre>
	 * 停止所有任务
	 * </pre>
	 */
	public static void stopAllTask()
	{
		Set<String> keySet = new HashSet<String>();
		for (Iterator<String> iter = taskMap.keySet().iterator(); iter.hasNext();)
		{
			String element = iter.next();
			keySet.add(element);
		}
		for (Iterator<String> iter = keySet.iterator(); iter.hasNext();)
		{
			String element = iter.next();
			ScheduleExcute.stopTaskByName(element);
		}
		keySet = null;
		logger.info("所有任务调度关闭完毕.");
	}

	/**
	 * <pre>
	 * 停止以任务调度名称指定的任务
	 * </pre>
	 * @param taskName 任务调度名称
	 */
	public static void stopTaskByName(String taskName)
	{
		try
		{
			LotterySchedule logictask = (LotterySchedule) taskMap.get(taskName);
			if (logictask != null)
			{
				logictask.cancel();
				logictask = null;
				taskMap.remove(taskName);
				ScheduleConfig lconfig = (ScheduleConfig) configMap.get(taskName);
				if (lconfig != null)
				{
					lconfig.setNextRuntime(0);
				}
				logger.info("任务调度[" + taskName + "]成功关闭.");
			}
		}
		catch (Exception e)
		{
			logger.error("停止任务调度的时候异常.", e);
		}
	}
}
